/**
 * Author: luoqi
 * Created Date: 2025-10-15 22:58:17
 * Last Modified: 2025-11-06 00:01:28
 * Modified By: luoqi at <**@****>
 * Copyright (c) 2025 <*****>
 * Description:
 */

#include <dev/xbot.h>
#include "cmds.hpp"

static QShell &cli = QShellObj::obj();
static CanPort canfd = XBotObj::obj().canfd;

static int args_send(int argc, char **argv)
{
    if(argc != 3) {
        return -1;
    }
    int id = strtol(argv[1], nullptr, 0);
    int len = strlen(argv[2]);
    if(len > 64) {
        len = 64;
    }

    canfd.send(id, (uint8_t *)argv[2], len);
    return 0;
}

static int args_recv(int argc, char **argv)
{
    if(argc != 2) {
        return -1;
    }
    int timeout_ms = strtod(argv[1], nullptr);
    uint16_t id;
    uint8_t rbuf[64];
    uint8_t sz;
    int nbytes = canfd.recv(id, rbuf, sz, timeout_ms);
    if(nbytes < 0) {
        return -1;
    } else if(nbytes == 0) {
        cli.print(" -timeout: %d ms\r\n", timeout_ms);
        return 0;
    } else {
        
    }
    cli.print("id: 0x%04x, sz: %d, data: ", id, sz);
    for(int i = 0; i < sz; i++) {
        cli.print("%02x ", rbuf[i]);
    }
    cli.print("\r\n");
    return 0;
}

static std::thread thr_stress;
static bool stress_running = false;
static int64_t ms = 10;

static void canport_stress_hdl()
{
    stress_running = true;
    uint8_t data[64] = { 0 };
    uint16_t id;
    for(int i = 0; i < sizeof(data); i++) {
        data[i] = i;
    }
    while(stress_running) {
        canfd.send(id, data, sizeof(data));
        int p = id % 64;
        data[p]++;
        id++;
        std::this_thread::sleep_for(std::chrono::milliseconds(ms));
    }
}

static int args_sstress(int argc, char **argv)
{
    if(argc != 2 && argc != 3) {
        return -1;
    }
    if(ISARG(argv[1], "on") && (argc == 3)) {
        stress_running = false;
        std::this_thread::sleep_for(std::chrono::milliseconds(ms * 2));
        ms = strtol(argv[2], nullptr, 10);
        thr_stress = std::thread(canport_stress_hdl);
        thr_stress.detach();
    } else if(strcmp(argv[1], "off") == 0) {
        stress_running = false;
    } else {
        return -1;
    }
    return 0;
}

static QShell::ArgsTable table[] = {
    {"send", args_send, "send <id> <data>"},
    {"recv", args_recv, "<timeout_ms>"},
    {"stress", args_sstress, "<on|off> <ms>"},
};

int cmd_canport_hdl(int argc, char **argv)
{
    if(argc == 1) {
        return 0;
    }
    ARGS_TABLE_EXEC(cli, argc, argv, table);
}

EXPORT_CMD("canport", cmd_canport_hdl, "canport cmds");
